/**
 * Licensed to Inspektr under one or more contributor license
 * agreements. See the NOTICE file distributed with this work
 * for additional information regarding copyright ownership.
 * Inspektr licenses this file to you under the Apache License,
 * Version 2.0 (the "License"); you may not use this file
 * except in compliance with the License. You may obtain a
 * copy of the License at:
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package com.sunkey.log.audit.spi.support;

import java.util.HashMap;
import java.util.Map;

import org.aspectj.lang.JoinPoint;

import com.sunkey.log.audit.annotation.Audit;
import com.sunkey.log.audit.spi.AuditResourceResolver;
import com.sunkey.log.util.JsonUtil;
import com.sunkey.log.util.StringUtils;

/**
 * Abstract AuditResourceResolver for when the resource is the same regardless of an exception or not.
 * 
 * @author sunkey
 * @date Aug 25, 2014
 */
public abstract class AbstractAuditMixResourceResolver implements AuditResourceResolver {

    private int returnMaxSize = 1024;

    public final String[] resolveFrom(final JoinPoint joinPoint, final Object retVal, Audit audit) {
        String[] results = new String[2];
        if (audit != null && StringUtils.isNotBlank(audit.message())) {
            results[0] = "params:" + audit.message();
        } else {
            String params = createResource(joinPoint.getArgs());
            results[0] = "params:" + params;
        }
        if (retVal != null) {
            String result = getResult(retVal);
            if (getReturnMaxSize() > 0 && result.length() > getReturnMaxSize()) {
                result = result.substring(0, getReturnMaxSize());
            }
            results[1] = "result:" + result;
        }
        return results;
    }

    public final String[] resolveFrom(final JoinPoint joinPoint, final Exception e, Audit audit) {
        Map<String, String> map = new HashMap<String, String>();
        if (audit != null && StringUtils.isNotBlank(audit.message())) {
            map.put("params", audit.message());
        } else {
            String params = createResource(joinPoint.getArgs());
            map.put("params", params);
        }
        map.put("result", getResult(e.getMessage()));
        return new String[] { JsonUtil.toJson(map) };
    }

    private String getResult(final Object retVal) {
        if (retVal instanceof String) {
            return StringUtils.replaceBlank(retVal.toString());
        } else {
            return JsonUtil.toJson(retVal);
        }
    }

    @Override
    public String[] resolveFrom(JoinPoint target, Object returnValue) {
        return resolveFrom(target, returnValue, null);
    }

    @Override
    public String[] resolveFrom(JoinPoint target, Exception exception) {
        return resolveFrom(target, exception, null);
    }

    protected abstract String createResource(final Object[] args);

    protected int getReturnMaxSize() {
        return returnMaxSize;
    };
}
